package com.qzh.G.base;

import com.qzh.G.Equipment;
import com.qzh.G.Item;
import com.qzh.G.constants.Limits;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 活动对象
 */
@Data
@NoArgsConstructor
public class ActiveObject implements AttackAble,HurtAble, HealAble,equipmentAble,Itemable {
    private long id;
    private String name;
    private String description;
    private List<Item> box;
    private BigDecimal baseAttack;//gong
    private BigDecimal baseDefend;//fang
    private BigDecimal base_chr;//baojilv
    private BigDecimal base_chd;//baoshang
    private BigDecimal base_dodge_rate;//shanbi
    private BigDecimal base_hp;
    private BigDecimal base_hpLimit;
    private BigDecimal attack;
    private BigDecimal defend;
    private BigDecimal chr;
    private BigDecimal chd;
    private BigDecimal dodge_rate;
    private BigDecimal hp;
    private BigDecimal hpLimit;
    ////////////////以下属性无基础值////////////////
    /**
     * 伤害增幅比例
     */
    private  BigDecimal damageRate;
    /**
     *减伤比例
     */
    private BigDecimal reduceRate;
    /**
     *保底伤害比例
     */
    private BigDecimal minDamageRate;

    private Equipment weapon;
    private Equipment shield;
    private Equipment ring;
    private Equipment earing;
    private Equipment armor;
    private Equipment shoes;
    private Equipment helmet;

    ActiveObject(long id){
        this.id = id;
        this.box = new ArrayList<>();
    }


    @Override
    public Attack SingleAttack(Long id) {
        return null;
    }

    @Override
    public List<Attack> MultiAttack(List[] ids) {
        return null;
    }

    @Override
    public AttackResult getHurt(Attack attack) {
return  null;
    }
   void death(){}

    @Override
    public Attack heal(long id) {
        return null;
    }

    @SneakyThrows
    @Override
    public void equip(Equipment equipment) {
        switch (equipment.getEquipmentType()){
            case ring:setRing(equipment);
                break;
            case armor:setArmor(equipment);
                break;
            case shoes:setShoes(equipment);
                break;
            case earing:setEaring(equipment);
                break;
            case helmet:setHelmet(equipment);
                break;
            case shield:setShield(equipment);
                break;
            case weapon:setWeapon(equipment);
                break;
        }
        for (Effect e:equipment.getEffectList()){
                     switch (e.getTarType()){
                         case hp: BigDecimal newVal = getValue(e,getHp(),BaseType.hp);
                                        if(newVal.compareTo(BigDecimal.ZERO)<=0){death();}if(newVal.compareTo(getHpLimit())>=1){newVal = getHpLimit();}
                                        setHp(newVal);
                             break;
                         case chr:BigDecimal newVal2 = getValue(e,getChr(),BaseType.chr);
                             if(newVal2.compareTo(Limits.chr_limit_down)<=0){newVal2 = Limits.chr_limit_down;}if(newVal2.compareTo(Limits.chr_limit_up)>=1){newVal2 = Limits.chr_limit_up;}
                             setChr(newVal2);
                             break;
                         case chd:BigDecimal newVal3 = getValue(e,getChd(),BaseType.chd);
                             if(newVal3.compareTo(Limits.chd_limit_down)<=0){newVal3 = Limits.chd_limit_down;}if(newVal3.compareTo(Limits.chd_limit_up)>=1){newVal3 = Limits.chd_limit_up;}
                             setChd(newVal3);
                             break;
                         case attack:BigDecimal newVal4 = getValue(e,getAttack(),BaseType.atk);
                             if(newVal4.compareTo(Limits.atk_limit_down)<=0){newVal4 = Limits.atk_limit_down;}if(newVal4.compareTo(Limits.atk_limit_up)>=1){newVal4= Limits.atk_limit_up;}
                             setAttack(newVal4);
                             break;
                         case defend:BigDecimal newVal5 = getValue(e,getDefend(),BaseType.def);
                             if(newVal5.compareTo(Limits.def_limit_down)<=0){newVal5 = Limits.def_limit_down;}if(newVal5.compareTo(Limits.def_limit_up)>=1){newVal5 = Limits.def_limit_up;}
                             setDefend(newVal5);
                             break;
                         case hpLimit:BigDecimal newVal6 = getValue(e,getHpLimit(),BaseType.hpLimt);
                             if(newVal6.compareTo(Limits.hp_limit_down)<=0){newVal6 = Limits.hp_limit_down;}if(newVal6.compareTo(Limits.hp_limit_up)>=1){newVal6 = Limits.hp_limit_up;}
                             setHpLimit(newVal6);
                             break;
                         case damageRate:BigDecimal newVal7 = getValue(e,getDamageRate(),BaseType.damageRate);
                             if(newVal7.compareTo(Limits.damage_buff_limit_down)<=0){newVal7 = Limits.damage_buff_limit_down;}if(newVal7.compareTo(Limits.damage_buff_limit_up)>=1){newVal7 = Limits.damage_buff_limit_up;}
                             setDamageRate(newVal7);
                             break;
                         case dodge_rate:BigDecimal newVal8 = getValue(e,getDodge_rate(),BaseType.dodge);
                             if(newVal8.compareTo(Limits.dodge_limit_down)<=0){newVal8 = Limits.dodge_limit_down;}if(newVal8.compareTo(Limits.dodge_limit_up)>=1){newVal8 = Limits.dodge_limit_up;}
                             setDodge_rate(newVal8);
                             break;
                         case reduceRate:BigDecimal newVal9 = getValue(e,getReduceRate(),BaseType.reduceRate);
                             if(newVal9.compareTo(Limits.reduce_damage_limit_down)<=0){newVal9 = Limits.reduce_damage_limit_down;}if(newVal9.compareTo(Limits.reduce_damage_limit_up)>=1){newVal9 = Limits.reduce_damage_limit_up;}
                             setReduceRate(newVal9);
                             break;
                         case minDamageRate:BigDecimal newVal10 = getValue(e,getMinDamageRate(),BaseType.minRate);
                             if(newVal10.compareTo(Limits.min_damage_limit_down)<=0){newVal10 = Limits.min_damage_limit_down;}if(newVal10.compareTo(Limits.min_damage_limit_up)>=1){newVal10 = Limits.min_damage_limit_up;}
                             setMinDamageRate(newVal10);
                             break;
                         case equipment:
                             break;
                         case BaseObject:
                             break;
                     }
                     }

    }

    /**
     * 装备后的效果新制
     * @param effect
     * @param old
     * @param baseType
     * @return
     */
    private BigDecimal getValue(Effect effect,BigDecimal old,BaseType baseType){
                        switch (baseType){
                            case hp:   switch (effect.getType()){
                                case base:   switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getBase_hp().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                                case present:  switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getHp().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                            }break;
                            case chd:   switch (effect.getType()){
                                case base:   switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getBase_chd().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                                case present:  switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getChd().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                            }break;
                            case chr:   switch (effect.getType()){
                                case base:   switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getBase_chr().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                                case present:  switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getChr().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                            }break;
                            case atk:   switch (effect.getType()){
                                case base:   switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getBaseAttack().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                                case present:  switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getAttack().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                            }break;
                            case def:   switch (effect.getType()){
                                case base:   switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getBaseDefend().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                                case present:  switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getDefend().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                            }break;
                            case dodge:   switch (effect.getType()){
                                case base:   switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getBase_dodge_rate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                                case present:  switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getDodge_rate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                            }break;
                            case hpLimt:   switch (effect.getType()){
                                case base:   switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getBase_hpLimit().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                                case present:  switch (
                                        effect.getCalcType()){
                                    case add:return old.add(effect.getValue());
                                    case multi:return old.add(getHpLimit().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                                    break;
                            }break;
                            case damageRate: switch (
                                    effect.getCalcType()){
                                case add:return old.add(effect.getValue());
                                case multi:return old.add(getDamageRate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                            case reduceRate: switch (
                                    effect.getCalcType()){
                                case add:return old.add(effect.getValue());
                                case multi:return old.add(getReduceRate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                            case minRate: switch (
                                    effect.getCalcType()){
                                case add:return old.add(effect.getValue());
                                case multi:return old.add(getMinDamageRate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                        }
                return BigDecimal.ZERO;
    }

    /**
     * 卸载装备后需要恢复原值。
     * @param effect
     * @param old
     * @param baseType
     * @return
     */
    private BigDecimal getOppoValue(Effect effect,BigDecimal old,BaseType baseType){
        switch (baseType){
            case hp:   switch (effect.getType()){
                case base:   switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getBase_hp().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
                case present:  switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getHp().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
            }break;
            case chd:   switch (effect.getType()){
                case base:   switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getBase_chd().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
                case present:  switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getChd().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
            }break;
            case chr:   switch (effect.getType()){
                case base:   switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getBase_chr().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
                case present:  switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getChr().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
            }break;
            case atk:   switch (effect.getType()){
                case base:   switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getBaseAttack().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
                case present:  switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getAttack().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
            }break;
            case def:   switch (effect.getType()){
                case base:   switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getBaseDefend().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
                case present:  switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getDefend().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
            }break;
            case dodge:   switch (effect.getType()){
                case base:   switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getBase_dodge_rate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
                case present:  switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getDodge_rate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
            }break;
            case hpLimt:   switch (effect.getType()){
                case base:   switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getBase_hpLimit().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
                case present:  switch (
                        effect.getCalcType()){
                    case add:return old.subtract(effect.getValue());
                    case multi:return old.subtract(getHpLimit().multiply(BigDecimal.ZERO.add(effect.getValue())));}
                    break;
            }break;
            case damageRate: switch (
                    effect.getCalcType()){
                case add:return old.subtract(effect.getValue());
                case multi:return old.subtract(getDamageRate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
            case reduceRate: switch (
                    effect.getCalcType()){
                case add:return old.subtract(effect.getValue());
                case multi:return old.subtract(getReduceRate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
            case minRate: switch (
                    effect.getCalcType()){
                case add:return old.subtract(effect.getValue());
                case multi:return old.subtract(getMinDamageRate().multiply(BigDecimal.ZERO.add(effect.getValue())));}
        }
        return BigDecimal.ZERO;
    }

    @Override
    public void addItemToBox(Item item) {
                box.add(item);
    }

    @Override
    public void removeItemToBox(Item item) {
                if(!item.getLock()){
                    box.remove(item);
                }
    }

    @Override
    public void useItemToBox(Item item) {
                    if(item.getUseAble()){
                       {
                            for(Effect e:item.getEffectList()){
                                switch (e.getTarType()){
                                    case hp: BigDecimal newVal = getValue(e,getHp(),BaseType.hp);
                                        if(newVal.compareTo(BigDecimal.ZERO)<=0){death();}if(newVal.compareTo(getHpLimit())>=1){newVal = getHpLimit();}
                                        setHp(newVal);
                                        break;
                                    case chr:BigDecimal newVal2 = getValue(e,getChr(),BaseType.chr);
                                        if(newVal2.compareTo(Limits.chr_limit_down)<=0){newVal2 = Limits.chr_limit_down;}if(newVal2.compareTo(Limits.chr_limit_up)>=1){newVal2 = Limits.chr_limit_up;}
                                        setChr(newVal2);
                                        break;
                                    case chd:BigDecimal newVal3 = getValue(e,getChd(),BaseType.chd);
                                        if(newVal3.compareTo(Limits.chd_limit_down)<=0){newVal3 = Limits.chd_limit_down;}if(newVal3.compareTo(Limits.chd_limit_up)>=1){newVal3 = Limits.chd_limit_up;}
                                        setChd(newVal3);
                                        break;
                                    case attack:BigDecimal newVal4 = getValue(e,getAttack(),BaseType.atk);
                                        if(newVal4.compareTo(Limits.atk_limit_down)<=0){newVal4 = Limits.atk_limit_down;}if(newVal4.compareTo(Limits.atk_limit_up)>=1){newVal4= Limits.atk_limit_up;}
                                        setAttack(newVal4);
                                        break;
                                    case defend:BigDecimal newVal5 = getValue(e,getDefend(),BaseType.def);
                                        if(newVal5.compareTo(Limits.def_limit_down)<=0){newVal5 = Limits.def_limit_down;}if(newVal5.compareTo(Limits.def_limit_up)>=1){newVal5 = Limits.def_limit_up;}
                                        setDefend(newVal5);
                                        break;
                                    case hpLimit:BigDecimal newVal6 = getValue(e,getHpLimit(),BaseType.hpLimt);
                                        if(newVal6.compareTo(Limits.hp_limit_down)<=0){newVal6 = Limits.hp_limit_down;}if(newVal6.compareTo(Limits.hp_limit_up)>=1){newVal6 = Limits.hp_limit_up;}
                                        setHpLimit(newVal6);
                                        break;
                                    case damageRate:BigDecimal newVal7 = getValue(e,getDamageRate(),BaseType.damageRate);
                                        if(newVal7.compareTo(Limits.damage_buff_limit_down)<=0){newVal7 = Limits.damage_buff_limit_down;}if(newVal7.compareTo(Limits.damage_buff_limit_up)>=1){newVal7 = Limits.damage_buff_limit_up;}
                                        setDamageRate(newVal7);
                                        break;
                                    case dodge_rate:BigDecimal newVal8 = getValue(e,getDodge_rate(),BaseType.dodge);
                                        if(newVal8.compareTo(Limits.dodge_limit_down)<=0){newVal8 = Limits.dodge_limit_down;}if(newVal8.compareTo(Limits.dodge_limit_up)>=1){newVal8 = Limits.dodge_limit_up;}
                                        setDodge_rate(newVal8);
                                        break;
                                    case reduceRate:BigDecimal newVal9 = getValue(e,getReduceRate(),BaseType.reduceRate);
                                        if(newVal9.compareTo(Limits.reduce_damage_limit_down)<=0){newVal9 = Limits.reduce_damage_limit_down;}if(newVal9.compareTo(Limits.reduce_damage_limit_up)>=1){newVal9 = Limits.reduce_damage_limit_up;}
                                        setReduceRate(newVal9);
                                        break;
                                    case minDamageRate:BigDecimal newVal10 = getValue(e,getMinDamageRate(),BaseType.minRate);
                                        if(newVal10.compareTo(Limits.min_damage_limit_down)<=0){newVal10 = Limits.min_damage_limit_down;}if(newVal10.compareTo(Limits.min_damage_limit_up)>=1){newVal10 = Limits.min_damage_limit_up;}
                                        setMinDamageRate(newVal10);
                                        break;
                                    case equipment:
                                        break;
                                    case BaseObject:
                                        break;

                                }
                            }
                            removeItemToBox(item);
                        }

                    }
    }

    /**
     * 属性类型
     */
    enum BaseType{
        hp,atk,def,chr,chd,hpLimt,dodge,damageRate,minRate,reduceRate
    }
    @Override
    public void unEquip(Equipment equipment) {
        switch (equipment.getEquipmentType()){
            case ring:setRing(null);
                break;
            case armor:setArmor(null);
                break;
            case shoes:setShoes(null);
                break;
            case earing:setEaring(null);
                break;
            case helmet:setHpLimit(null);
                break;
            case shield:setShield(null);
                break;
            case weapon:setWeapon(null);
                break;
        }
        for (Effect e:equipment.getEffectList()){
            switch (e.getTarType()){
                case hp: BigDecimal newVal = getOppoValue(e,getHp(),BaseType.hp);
                    if(newVal.compareTo(BigDecimal.ZERO)<=0){death();}if(newVal.compareTo(getHpLimit())>=1){newVal = getHpLimit();}
                    setHp(newVal);
                    break;
                case chr:BigDecimal newVal2 = getOppoValue(e,getChr(),BaseType.chr);
                    if(newVal2.compareTo(Limits.chr_limit_down)<=0){newVal2 = Limits.chr_limit_down;}if(newVal2.compareTo(Limits.chr_limit_up)>=1){newVal2 = Limits.chr_limit_up;}
                    setChr(newVal2);
                    break;
                case chd:BigDecimal newVal3 = getOppoValue(e,getChd(),BaseType.chd);
                    if(newVal3.compareTo(Limits.chd_limit_down)<=0){newVal3 = Limits.chd_limit_down;}if(newVal3.compareTo(Limits.chd_limit_up)>=1){newVal3 = Limits.chd_limit_up;}
                    setChd(newVal3);
                    break;
                case attack:BigDecimal newVal4 = getOppoValue(e,getAttack(),BaseType.atk);
                    if(newVal4.compareTo(Limits.atk_limit_down)<=0){newVal4 = Limits.atk_limit_down;}if(newVal4.compareTo(Limits.atk_limit_up)>=1){newVal4= Limits.atk_limit_up;}
                    setAttack(newVal4);
                    break;
                case defend:BigDecimal newVal5 = getOppoValue(e,getDefend(),BaseType.def);
                    if(newVal5.compareTo(Limits.def_limit_down)<=0){newVal5 = Limits.def_limit_down;}if(newVal5.compareTo(Limits.def_limit_up)>=1){newVal5 = Limits.def_limit_up;}
                    setDefend(newVal5);
                    break;
                case hpLimit:BigDecimal newVal6 = getOppoValue(e,getHpLimit(),BaseType.hpLimt);
                    if(newVal6.compareTo(Limits.hp_limit_down)<=0){newVal6 = Limits.hp_limit_down;}if(newVal6.compareTo(Limits.hp_limit_up)>=1){newVal6 = Limits.hp_limit_up;}
                    setHpLimit(newVal6);
                    break;
                case damageRate:BigDecimal newVal7 = getOppoValue(e,getDamageRate(),BaseType.damageRate);
                    if(newVal7.compareTo(Limits.damage_buff_limit_down)<=0){newVal7 = Limits.damage_buff_limit_down;}if(newVal7.compareTo(Limits.damage_buff_limit_up)>=1){newVal7 = Limits.damage_buff_limit_up;}
                    setDamageRate(newVal7);
                    break;
                case dodge_rate:BigDecimal newVal8 = getOppoValue(e,getDodge_rate(),BaseType.dodge);
                    if(newVal8.compareTo(Limits.dodge_limit_down)<=0){newVal8 = Limits.dodge_limit_down;}if(newVal8.compareTo(Limits.dodge_limit_up)>=1){newVal8 = Limits.dodge_limit_up;}
                    setDodge_rate(newVal8);
                    break;
                case reduceRate:BigDecimal newVal9 = getOppoValue(e,getReduceRate(),BaseType.reduceRate);
                    if(newVal9.compareTo(Limits.reduce_damage_limit_down)<=0){newVal9 = Limits.reduce_damage_limit_down;}if(newVal9.compareTo(Limits.reduce_damage_limit_up)>=1){newVal9 = Limits.reduce_damage_limit_up;}
                    setReduceRate(newVal9);
                    break;
                case minDamageRate:BigDecimal newVal10 = getOppoValue(e,getMinDamageRate(),BaseType.minRate);
                    if(newVal10.compareTo(Limits.min_damage_limit_down)<=0){newVal10 = Limits.min_damage_limit_down;}if(newVal10.compareTo(Limits.min_damage_limit_up)>=1){newVal10 = Limits.min_damage_limit_up;}
                    setMinDamageRate(newVal10);
                    break;
                case equipment:
                    break;
                case BaseObject:
                    break;
            }
        }
    }
}
